/*这段代码的作用是通过共享内存实现父进程和子进程之间的通信。具体而言，代码分为父进程和子进程两部分，它们之间通过共享内存传递消息。

以下是代码的执行流程：

父进程首先创建一个共享内存段，使用shmget函数，并获得一个唯一的共享内存标识符（shmid）。

父进程创建子进程，使用fork函数。子进程的执行流程与父进程分开。

在子进程中，它首先延迟一定时间（DELAY_TIME）后执行。然后，它通过shmat函数连接到父进程创建的共享内存段，获取共享内存区域的指针（shm_addr）。

子进程从共享内存中复制消息到本地的缓冲区（buff），使用strcpy函数。然后，它打印接收到的消息。

子进程断开与共享内存的连接，使用shmdt函数。

子进程退出。

在父进程中，它首先连接到先前创建的共享内存段，使用shmat函数，获取共享内存区域的指针（shm_addr）。

父进程提示用户输入消息，并将输入的消息存储到缓冲区（buff）中，使用fgets函数。

父进程将缓冲区中的消息复制到共享内存中，使用strncpy函数。

父进程断开与共享内存的连接，使用shmdt函数。

父进程等待子进程结束，使用waitpid函数。

父进程删除共享内存段，使用shmctl函数，并将其标记为删除。

父进程退出。

总结来说，该段代码通过共享内存实现了父子进程之间的通信。父进程将用户输入的消息存储到共享内存中，子进程从共享内存中读取并打印接收到的消息。这样，父子进程就可以通过共享内存传递数据。
*/



#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>

#define DELAY_TIME 10
#define SIZE 2048

int main(){
    pid_t pid;                   // 进程ID类型的变量，用于存储fork()函数的返回值
    int shmid;                   // 共享内存标识符
    char *shm_addr;              // 指向共享内存区域的指针
    char buff[SIZE];             // 存储输入和传输的消息的缓冲区

    // 创建共享内存段
    if ((shmid=shmget(IPC_PRIVATE, SIZE, 0666))<0){
        perror("shmget");
        exit(-1);
    } else
        printf("Create shared memory: %d.\n",shmid);


    // 创建子进程
    if ((pid=fork())<0){
        perror("fork");
        exit(1);
    }else if (pid==0){
        sleep(DELAY_TIME);
        printf("1.In child process:\n");
        // 连接到共享内存
        if ((shm_addr=shmat(shmid,0,0))==(void*)-1){
            perror("shmat");   
            exit(-1);
        }
        
        strcpy(buff,shm_addr);       // 从共享内存中复制消息到缓冲区
        printf("Child receive:%s\n",buff);

        // 断开与共享内存的连接
        if (shmdt(shm_addr)<0){
            perror("shmdt");   
            exit(-1);
        }
        exit(0);
    }else{
        printf("In parent process:\n");
        // 连接到共享内存
        if ((shm_addr=shmat(shmid,0,0))==(void*)-1){
            perror("shmat");   
            exit(-1);
        }

        printf("\nInput msg:\n");
        fgets(buff,SIZE,stdin);      // 从标准输入读取用户输入的消息
        strncpy(shm_addr,buff,strlen(buff));  // 将消息复制到共享内存中

        // 断开与共享内存的连接
        if (shmdt(shm_addr)<0){
            perror("shmdt");   
            exit(-1);
        }

        waitpid(pid,NULL,0);        // 等待子进程结束
        
        // 删除共享内存
        if (shmctl(shmid,IPC_RMID,NULL)==-1){
            perror("shmctl");   
            exit(-1);
        }        

        exit(0);
    }

    return 0;
}
